package cn.tedu.core;

import cn.tedu.http.HttpRequest;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;

/**
 * Author：程Sir
 * Name： SmallServer
 * Content:
 *  负责与指定客户端进行HTTP交互
 *     该线程将来与客户端交互的过程必须遵守HTTP协议要求，采取一问一答的方式进行,固定的解析步骤：
 *     1. 解析请求【问】
 *     2. 处理请求
 *     3. 响应请求【答】
 *
 *
 *
 */
public class RequestHandler implements Runnable {
    // 声明全局变量socket [socket中包含了所有客户端的请求信息]
    private Socket socket;
    public RequestHandler(Socket socket){
        this.socket = socket;
    }
    @Override
    public void run() {

        // 1.请求解析
        HttpRequest httpRequest = new HttpRequest(socket);

        // 2. 处理请求
        // 首先通过 httpRequest 获取请求中的抽象路径
        String url = httpRequest.getUrl();
        /*
            ./webapps/ 可以认为是一个固定的资源请求服务器，需要某个应用的资源文件，就可以在此服务器下面查找
            要求客户端输入请求资源时，一并要输入应用的名称例如：
                应用是找：myweb
                资源是找：index.html
                客户端发送的请求就应是： http://localhost:8080/myweb/index.html
         */
        File  file = new File("./webapps/"+url);

        // 若该资源存在且是一个文件，则正常做出响应
        // 3.做出响应
        if(file.exists() && file.isFile()){
            System.out.println("资源是存在的，下面进行反馈...");
            /*
            做实体资源的响应, 测试：先反馈给客户端一个正确的资源
            （1）状态行
            （2）响应头
            （3）响应正文
         */
            // 获取输出流
            try {
                OutputStream outputStream = socket.getOutputStream();
                // 1.状态行内容
                String line="HTTP/1.1 200 OK";
                // 将字符串转换为byte数组
                byte[] bytes = line.getBytes("ISO8859-1");
                outputStream.write(bytes);
                // 状态行的标志是发送一个CRLF的连续字符
                outputStream.write(13); // CR
                outputStream.write(10); // LF

                // 2.响应头内容
                line = "Content-Type: text/html";
                bytes = line.getBytes("ISO8859-1");
                outputStream.write(bytes);
                outputStream.write(13); // CR
                outputStream.write(10); // LF

                line = "Content-Length: "+file.length();
                bytes = line.getBytes("ISO8859-1");
                outputStream.write(bytes);
                outputStream.write(13); // CR
                outputStream.write(10); // LF

                // 响应头信息全部发送完毕的标识是：单独发生一个连续的字符标识CRLF
                outputStream.write(13); // CR
                outputStream.write(10); // LF

                //3. 响应正文
                // 创建文件输入流读取要发生给客户端的资源数据
                FileInputStream fileInputStream = new FileInputStream(file);
                byte[] buf = new byte[5 * 1024];
                // 定义一个表示符：每次读取的字节数
                int len;
                while ((len= fileInputStream.read(buf)) !=-1){
                    // 将读到的数据写出
                    outputStream.write(buf,0,len);
                }
                System.out.println("数据响应完毕！");

            } catch (IOException e) {
                e.printStackTrace();
            }

        }else { // 如果资源不存在或者访问的是一个目录，则反馈404页面
            System.out.println("资源不存在，做404页面输出....");
            file = new File("./webapps/commons/404.html");
            /*
            做实体资源的响应, 测试：先反馈给客户端一个正确的资源
            （1）状态行
            （2）响应头
            （3）响应正文
         */
            // 获取输出流
            try {
                OutputStream outputStream = socket.getOutputStream();
                // 1.状态行内容
                String line="HTTP/1.1 200 OK";
                // 将字符串转换为byte数组
                byte[] bytes = line.getBytes("ISO8859-1");
                outputStream.write(bytes);
                // 状态行的标志是发送一个CRLF的连续字符
                outputStream.write(13); // CR
                outputStream.write(10); // LF

                // 2.响应头内容
                line = "Content-Type: text/html";
                bytes = line.getBytes("ISO8859-1");
                outputStream.write(bytes);
                outputStream.write(13); // CR
                outputStream.write(10); // LF

                line = "Content-Length: "+file.length();
                bytes = line.getBytes("ISO8859-1");
                outputStream.write(bytes);
                outputStream.write(13); // CR
                outputStream.write(10); // LF

                // 响应头信息全部发送完毕的标识是：单独发生一个连续的字符标识CRLF
                outputStream.write(13); // CR
                outputStream.write(10); // LF

                //3. 响应正文
                // 创建文件输入流读取要发生给客户端的资源数据
                FileInputStream fileInputStream = new FileInputStream(file);
                byte[] buf = new byte[5 * 1024];
                // 定义一个表示符：每次读取的字节数
                int len;
                while ((len= fileInputStream.read(buf)) !=-1){
                    // 将读到的数据写出
                    outputStream.write(buf,0,len);
                }
                System.out.println("404数据页面响应完毕！");

            } catch (IOException e) {
                e.printStackTrace();
            }
        }




    }


}
